#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <string.h>
#include <iostream>
#include <file_common.h>

using namespace std;

static int GetAbsolutePath(const char * relative, const char * path, char * absolute)
{
    strcpy(absolute, relative);
    strcat(absolute, "/");
    strcat(absolute, path);

    return 0;
}

/*
* 遍历文件夹及其子文件夹，并传入操作文件的回调函数，和回调函数的参数
*/
int TraverseFolderAndSub(const char *path, int(*callback)(const char *, void *), void *param)
{
    // 参数合法性校验
    if(!IsPathIegal(path)){
        return -1;
    }

    // 生成目录指针
	DIR *dir = opendir(path);
    if(dir == NULL){
        return -2;
    }

	struct dirent *dirp;// 保存一个目录的属性
	while((dirp = readdir(dir)) != NULL){
        // 排除当前目录和上级目录
        if(strcmp(dirp->d_name,".") == 0 || 
           strcmp(dirp->d_name, "..") == 0){
            continue;
        }

        // 获取绝对路径
        char absPath[256];
        GetAbsolutePath(path, dirp->d_name, absPath);
        
        // 获取文件属性
        struct stat fileStat;
        lstat(absPath, &fileStat);

        // 遍历子文件夹
        if(S_ISDIR(fileStat.st_mode)){
            TraverseFolderAndSub(absPath, callback, param);
        }
        
        // 调用文件处理回调函数
        callback(absPath, param);
	}
    closedir(dir);

    return 0;
}

/*
* 遍历文件夹及其子文件夹
*/
int TraverseFolder(const char *path, int(*callback)(const char *, void *), void *param)
{
    // 参数合法性校验
    if(!IsPathIegal(path)){
        return -1;
    }

    // 遍历目录
	DIR *dir = opendir(path);
	struct dirent *dirp;
	while((dirp = readdir(dir)) != NULL){
        // 排除当前目录和上级目录
        if(strcmp(dirp->d_name,".") == 0 || 
           strcmp(dirp->d_name, "..") == 0){
        }
        callback(dirp->d_name, param);
	}
    closedir(dir);

    return 0;
}

bool IsPathIegal(const char *path)
{
    if(path == NULL){
        return false;
    }

    return true;
}

int CreateFloderIfNotExist(const char *path)
{
    // 参数合法性校验
    if(!IsPathIegal(path)){
        return -1;
    }
    
    // 确保文件有可读写权限
    if (!access(path, F_OK)){
        if(access(path, R_OK | W_OK | X_OK)){
            return chmod(path, S_IRWXU | S_IRWXG);
        }
    } else {
        return mkdir(path, S_IRWXU | S_IRWXG);
    }

    return 0;
}